package model.geneticAlgorithm.driver;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Timer;

import model.geneticAlgorithm.GeneticAlgorithm;
import model.geneticAlgorithm.selectionStrategies.OrganismSelectionStrategy;
import model.organism.Organism;
import model.population.Population;

public abstract class GeneticAlgorithmDriver implements GeneticAlgorithm
{
	private static int generationDuration = 30;	//length of one generation in milliseconds

	protected Population population;
	protected OrganismSelectionStrategy organismSelectionStrategy;
	protected int generation = 0;
	protected int generationToPause = generation;
	protected ActionListener timerListener = new ActionListener(){
		public void actionPerformed(ActionEvent evt) 
		{
			if(!evaluatePopulation() && ++generation < generationToPause)
			{
				produceNextGeneration();
			}
			else
			{

				generationTimer.stop();
			}
	    }
	};
	protected Timer generationTimer = new Timer(generationDuration, timerListener);
	
	public GeneticAlgorithmDriver()
	{
		generationTimer.setRepeats(true);
		initializePopulation();
	}
	
	@Override
	public Organism runForGenerations(int numberOfGenerations)
	{
		if(population == null) 
		{
			initializePopulation();
		}
		
		generationToPause = generation + numberOfGenerations;
		generationTimer.start();
		return null;
	}	

	public void setPopulation(Population population)
	{
		this.population = population;
	}
	
	public void setOrganismSelectionStrategy(OrganismSelectionStrategy newStrategy)
	{
		this.organismSelectionStrategy = newStrategy;
	}
	
	public Population getPopulation()
	{
		return population;
	}

	public OrganismSelectionStrategy getOrganismSelectionStrategy()
	{
		return organismSelectionStrategy;
	}
	
	public int getGeneration()
	{
		return generation;
	}
	
	protected abstract void initializePopulation();

	protected abstract boolean evaluatePopulation();

	protected abstract void produceNextGeneration();

}
